use once_cell::sync::Lazy;
use std::ptr::null_mut;
use std::sync::{Arc, Mutex};
use std::thread;
use std::thread::sleep;
use std::time::Duration;
use sysinfo::System;
use tauri::{AppHandle, Emitter, Runtime};
use winapi::shared::minwindef::HMODULE;
use winapi::um::handleapi::CloseHandle;
use winapi::um::handleapi::INVALID_HANDLE_VALUE;
use winapi::um::memoryapi::{ReadProcessMemory, WriteProcessMemory};
use winapi::um::processthreadsapi::OpenProcess;
use winapi::um::psapi::EnumProcessModules;
use winapi::um::winnt::{HANDLE, PROCESS_ALL_ACCESS};

static INFINITE_HEALTH: Lazy<Arc<Mutex<bool>>> = Lazy::new(|| Arc::new(Mutex::new(false)));
static INFINITE_MONEY: Lazy<Arc<Mutex<bool>>> = Lazy::new(|| Arc::new(Mutex::new(false)));
static ONE_HIT_KILL: Lazy<Arc<Mutex<bool>>> = Lazy::new(|| Arc::new(Mutex::new(false)));
static GLOBAL_PID: Lazy<Arc<Mutex<Option<u32>>>> = Lazy::new(|| Arc::new(Mutex::new(None)));

#[tauri::command]
pub fn set_infinite_health(enabled: bool) {
    let mut health = INFINITE_HEALTH.lock().unwrap();
    *health = enabled;
    println!("Infinite Health: {}", enabled);

    // 再检查 enabled 条件
    if enabled {
        // 检查全局 PID 是否有值
        let global_pid = GLOBAL_PID.lock().unwrap();
        if let Some(pid) = *global_pid {
            // 调用 write_memory 函数
            let address = 0x016272F8; // 指定地址
            let value = 1000; // 指定数值
            let success = write_memory(pid, address, value);
            println!("Write memory success: {}", success);
        } else {
            println!("No PID available to set infinite health.");
        }
    } else {
        println!("Condition enabled is false.");
    }
}

#[tauri::command]
pub fn set_infinite_money(enabled: bool) {
    let mut money = INFINITE_MONEY.lock().unwrap();
    *money = enabled;
    println!("Infinite Money: {}", enabled);

    if enabled {
        let global_pid = GLOBAL_PID.lock().unwrap();
        if let Some(pid) = *global_pid {
            // 启动一个新线程来定期修改内存
            thread::spawn(move || {
                let mut num = 0;
                while INFINITE_MONEY.lock().unwrap().clone() {
                    // 获取游戏进程基址
                    if let Some(process_base) = get_base_address(pid) {
                        println!("Process base address: {:X}", process_base);
                        // 基址和偏移的计算
                        let base_address = process_base + 0x009B4500;
                        println!("Calculated base address: {:X}", base_address);
                        let offsets = vec![0x50, 0x190, 0x178, 0x18, 0x178, 0x8, 0x3E8, 0x3B0];

                        // 从基址开始，按照偏移链逐步读取内存
                        let mut current_address = base_address;
                        let mut read_success = true; // 添加标志位追踪读取状态

                        for offset in offsets {
                            if let Some(next_address) = read_memory(pid, current_address) {
                                current_address = next_address as usize + offset;
                            } else {
                                num += 1;
                                println!(
                                    "Failed to read memory at address{:?}: {:X}",
                                    num, current_address
                                );
                                read_success = false; // 设置标志位为失败
                                break; // 立即退出循环
                            }
                        }

                        println!("Current address: {:X}", current_address);

                        // 只有在所有内存读取成功的情况下才写入金钱数值
                        if read_success {
                            let success = write_memory(pid, current_address, 99999);
                            println!("Write money value success: {}", success);
                        }
                    }

                    // 等待500毫秒
                    sleep(Duration::from_millis(5000));
                }
            });
        } else {
            println!("No PID available to set infinite money.");
        }
    }
}

#[tauri::command]
pub fn set_one_hit_kill(enabled: bool) {
    let mut one_hit_kill = ONE_HIT_KILL.lock().unwrap();
    *one_hit_kill = enabled;
    println!("One Hit Kill: {}", enabled);
}

#[tauri::command]
pub fn thread_main_loop<R: Runtime>(app_handle: AppHandle<R>) {
    // 克隆 app_handle 以便在新线程中使用
    let app_handle_clone = app_handle.clone();

    // 生成一个新线程来运行 main_loop
    thread::spawn(move || {
        main_loop(app_handle_clone);
    });
}

#[tauri::command]
pub fn main_loop<R: tauri::Runtime>(app_handle: AppHandle<R>) {
    println!("find exe");
    loop {
        let s = System::new_all();
        println!("find Kingdom Rush Vengeance.exe");
        let mut pids = Vec::new();
        for process in s.processes_by_name("Kingdom Rush Vengeance.exe".as_ref()) {
            println!("{} {:?}", process.pid(), process.name());
            pids.push(process.pid().as_u32());
        }
        if !pids.is_empty() {
            // 设置全局 PID 变量
            let mut global_pid = GLOBAL_PID.lock().unwrap();
            *global_pid = Some(pids[0]); // 假设我们只关心第一个找到的 PID
                                         // Emit an event with the PID to the frontend
            app_handle.emit("pid_found", pids.clone()).unwrap();
            println!("Global PID set to: {:?}", *global_pid);
            break;
        }
        sleep(Duration::from_millis(500));
    }
}

#[tauri::command]
pub fn get_base_address(pid: u32) -> Option<usize> {
    unsafe {
        let handle: HANDLE = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);
        if handle == INVALID_HANDLE_VALUE {
            return None;
        }
        let mut h_mod: [HMODULE; 1024] = [null_mut(); 1024];
        let mut cb_needed: u32 = 0;
        
        if EnumProcessModules(
            handle,
            h_mod.as_mut_ptr(),
            (h_mod.len() * std::mem::size_of::<HMODULE>()) as u32,
            &mut cb_needed
        ) != 0 {
            let module_count = cb_needed as usize / std::mem::size_of::<HMODULE>();
            
            // 遍历所有模块，找到游戏主模块
            for i in 0..module_count {
                let module_base = h_mod[i] as usize;
                println!("Module base address: {:X}", module_base);
                
                // 获取模块名称
                let mut module_name: [u16; 256] = [0; 256];
                let name_size = winapi::um::psapi::GetModuleBaseNameW(
                    handle,
                    h_mod[i],
                    module_name.as_mut_ptr(),
                    module_name.len() as u32
                );
                
                if name_size > 0 {
                    // 将宽字符转换为字符串进行比较
                    let module_name_str = String::from_utf16_lossy(&module_name[..name_size as usize]);
                    println!("Module name: {}", module_name_str);
                    
                    // 检查是否为目标模块
                    if module_name_str == "Kingdom Rush Vengeance.exe" {
                        println!("Found target module: {}", module_name_str);
                        CloseHandle(handle);
                        return Some(module_base);
                    }
                }
            }
            
            // 如果没有找到指定模块，返回第一个模块的基址
            let base_address = h_mod[0] as usize;
            CloseHandle(handle);
            return Some(base_address);
        }
        CloseHandle(handle);
        None
    }
}

#[tauri::command]
pub fn read_memory(pid: u32, address: usize) -> Option<u64> {
    unsafe {
        let handle: HANDLE = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);
        if handle.is_null() {
            return None;
        }
        let mut value: u64 = 0;
        let result = ReadProcessMemory(
            handle,
            address as *const _,
            &mut value as *mut _ as *mut _,
            std::mem::size_of::<u64>(),
            null_mut(),
        );
        CloseHandle(handle);
        if result != 0 {
            Some(value)
        } else {
            None
        }
    }
}

#[tauri::command]
pub fn write_memory(pid: u32, address: usize, value: u32) -> bool {
    unsafe {
        let handle: HANDLE = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);
        if handle.is_null() {
            return false;
        }
        let result = WriteProcessMemory(
            handle,
            address as *mut _,
            &value as *const _ as *const _,
            std::mem::size_of::<u32>(),
            null_mut(),
        );
        CloseHandle(handle);
        result != 0
    }
}
